package com.ld.shieldsb.common.web.util;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Deque;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ld.shieldsb.annotation.util.AnnotationUtil;
import com.ld.shieldsb.common.composition.util.SecurityUtil;
import com.ld.shieldsb.common.core.collections.ListUtils;
import com.ld.shieldsb.common.core.encryptor.EorEncryptor;
import com.ld.shieldsb.common.core.model.Description;
import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.reflect.ClassUtil;
import com.ld.shieldsb.common.core.util.ResultUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.core.util.date.DateUtil;
import com.ld.shieldsb.common.web.StaticParams;
import com.ld.shieldsb.common.web.exception.ParamsterValidException;
import com.ld.shieldsb.common.web.model.SysUser;
import com.ld.shieldsb.common.web.util.params.ParamsHandleResult;
import com.ld.shieldsb.common.web.util.params.ParamsHandler;
import com.ld.shieldsb.common.web.util.params.impl.DefaultParamsHandler;
import com.ld.shieldsb.dao.model.QueryModel;

import lombok.extern.slf4j.Slf4j;

/**
 * web应用常用工具封装类，此类已经聚合到composition.Global中了
 * 
 * @ClassName Web
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2018年7月2日 上午11:12:58
 *
 */
@Slf4j
public class Web {

    public static class Attr {
        public static final String SESSION_USER = "session_user"; // session中
        public static final String USERID = "userId";

        public static final String REQUEST_ATTR_WEBDORESULT = "request_attr_webDoResult"; // request中
        public static final String REQUEST_ATTR_QUERYLINK = "request_attr_queryLink"; // request中查询关联对象，值为boolean型

        public static final String SESSION_TOKEN_KEY = "session_csrf_shieldtoken"; // request中查询关联对象，值为boolean型

        public static final String ERROR_PARAMSTER_VALID_NONE = "1001"; // 参数不存在
        public static final String ERROR_PARAMSTER_VALID_UNEQUAL = "1002"; // 参数不相等
        public static final String ERROR_PARAMSTER_VALID_DECRYPT = "1003"; // 参数不能正常解密
    }

    public static class Property {
        public static final String CONFIG_ADMINPATH = "shieldsb.adminPath"; // 后台地址配置key
        public static final String CONFIG_FRONTPATH = "shieldsb.frontPath"; // 前台地址配置key
    }

    /**
     * 请求处理
     * 
     * @ClassName Request
     * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
     * @date 2018年6月14日 上午11:27:57
     *
     */
    public static class Request {
        /**
         * 执行成功及提示写入request的Attribute中
         * 
         * @Title success
         * @author 吕凯
         * @date 2018年6月14日 上午11:36:11
         * @param request
         * @param msg
         *            void
         */
        public static void success(HttpServletRequest request, String msg) {
            success(request, msg, null);
        }

        /**
         * 执行成功及提示写入request的Attribute中
         * 
         * @Title success
         * @author 吕凯
         * @date 2018年6月14日 上午11:36:43
         * @param request
         * @param msg
         * @param object
         *            void
         */
        public static void success(HttpServletRequest request, String msg, Object object) {
            Result result = ResultUtil.success(msg, object);
            if (request != null) {
                request.setAttribute(Attr.REQUEST_ATTR_WEBDORESULT, result);
            }
        }

        /**
         * 执行失败及提示写入request的Attribute中
         * 
         * @Title error
         * @author 吕凯
         * @date 2018年6月14日 上午11:37:01
         * @param request
         * @param msg
         *            void
         */
        public static void error(HttpServletRequest request, String msg) {
            error(request, msg, null);
        }

        /**
         * 执行失败及提示写入request的Attribute中
         * 
         * @Title error
         * @author 吕凯
         * @date 2018年6月14日 上午11:37:45
         * @param request
         * @param msg
         * @param object
         *            void
         */
        public static void error(HttpServletRequest request, String msg, Object object) {
            Result result = ResultUtil.error(msg, object);
            if (request != null) {
                request.setAttribute(Attr.REQUEST_ATTR_WEBDORESULT, result);
            }
        }

        /**
         * 返回结果
         * 
         * @Title result
         * @author 吕凯
         * @date 2018年6月22日 上午10:27:04
         * @param request
         * @param result
         *            void
         */
        public static void result(HttpServletRequest request, Result result) {
            if (result == null) {
                result = new Result();
                result.setSuccess(false);
            }
            if (request != null) {
                request.setAttribute(Attr.REQUEST_ATTR_WEBDORESULT, result);
            }
        }

        /**
         * 
         * 获取request的Attribute中的执行结果
         * 
         * @Title getWebDoResult
         * @author 吕凯
         * @date 2018年6月14日 上午11:37:52
         * @param request
         * @return Result
         */
        public static Result getWebDoResult(HttpServletRequest request) {
            Result result = (Result) request.getAttribute(Attr.REQUEST_ATTR_WEBDORESULT);
            return result;
        }

        /**
         * 获取相对项目的URI，即不带项目名
         * 
         * @Title getURI
         * @author 吕凯
         * @date 2018年7月20日 上午9:51:44
         * @param request
         * @return String
         */
        public static String getRelativeURI(HttpServletRequest request) {
//            String uri = request.getRequestURI().substring(request.getContextPath().length());
            String uri = request.getServletPath();
            return uri;
        }

        /**
         * 获取项目请求网址
         * 
         * @Title getBasePathUrl
         * @author 刘金浩
         * @date 2020年7月17日
         * @param request
         * @return String
         */
        public static String getBasePathUrl(HttpServletRequest request) {
            String path = request.getContextPath();
            String result = "%s://%s%s/";
            String scheme = request.getScheme();
            String serverName = request.getServerName();
            int serverPort = request.getServerPort();
            if (80 != serverPort) {
                path = ":" + serverPort + path;
            }
            return String.format(result, scheme, serverName, path);
        }

    }

    /**
     * 返回结果
     * 
     * @ClassName Response
     * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
     * @date 2018年6月14日 上午11:27:47
     *
     */
    public static class Response {
        public static Result success(String msg) {
            return success(msg, null);
        }

        public static Result success(String msg, Object object) {
            return ResultUtil.success(msg, object);
        }

        public static Result error(String msg) {
            return error(msg, null);
        }

        public static Result error(String msg, Object object) {
            return ResultUtil.error(msg, object);
        }

        /**
         * 返回结果(不带数据)
         * 
         * @Title result
         * @author 吕凯
         * @date 2018年6月19日 上午10:15:35
         * @param result
         * @return Result
         */
        public static Result result(Result result) {
            result.setData(null);
            return ResultUtil.result(result);
        }

        /**
         * 
         * 返回结果(带数据,基于数据安全此方法需慎用)
         * 
         * @Title resultWithData
         * @author 吕凯
         * @date 2020年4月13日 上午10:09:06
         * @param result
         * @return Result
         */
        public static Result resultWithData(Result result) {
            return ResultUtil.result(result);
        }

        public static Result success(ServletResponse response, String msg) {
            return success(response, msg, null);
        }

        public static Result success(ServletResponse response, String msg, Object obj) {
            return responseJson(response, msg, obj, true);
        }

        public static Result error(ServletResponse response, String msg) {
            return error(response, msg, null);
        }

        public static Result error(ServletResponse response, String msg, Object obj) {
            return responseJson(response, msg, obj, false);
        }

        /**
         * 以json格式将 结果写入respon中
         * 
         * @Title response
         * @author 吕凯
         * @date 2018年7月2日 上午11:05:28
         * @param response
         * @param msg
         * @param obj
         * @param success
         * @return Result
         */
        public static Result responseJson(ServletResponse response, String msg, Object obj, boolean success) {
            Result result;
            if (success) {
                result = success(msg, obj);
            } else {
                result = error(msg, obj);
            }
            try {
                response.setContentType("application/json; charset=utf-8");
                response.getWriter().print(JSON.toJSONString(result, SerializerFeature.BrowserCompatible));
            } catch (IOException e) {
                log.error("返回response结果出错！", e);
            }
            return result;
        }

        /**
         * 
         * response 输出
         * 
         * @Title responseJson
         * @author 刘金浩
         * @date 2019年7月4日 上午9:53:34
         * @param response
         * @param msg
         * @param obj
         * @param success
         * @return Result
         */
        public static void write(HttpServletResponse response, String content) {
            write(response, content, "text/html", "utf-8");
        }

        public static void write(HttpServletResponse response, String content, String contentType) {
            write(response, content, contentType, "utf-8");
        }

        public static void write(HttpServletResponse response, String content, String contentType, String encoding) {
            PrintWriter writer = null;
            try {
                response.setCharacterEncoding(encoding);
                response.setContentType(contentType);
                response.setHeader("Cache-Control", "no-store");
                writer = response.getWriter();
                writer.println(content);
                writer.flush();
            } catch (IOException e) {
                log.error("输出错误");
            }
        }

        /**
         * 跳转错误页
         * 
         * @Title forwardError
         * @author 吕凯
         * @date 2019年10月22日 下午4:54:28
         * @param message
         *            void
         */
        public static void forwardError(String message) {
            throw new RuntimeException(message); // 异常上抛，错误拦截器会拦截
        }

        public static String forwardJson(HttpServletRequest request, Result result) {
            request.setAttribute("result", result);
            return "forward:/scbase/jsonresult"; // 跳转提示页面,注意需要定义到具体的controller类中，否则报错
        }

    }

    /**
     * 工具类
     * 
     * @ClassName Util
     * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
     * @date 2018年4月28日 下午1:53:36
     *
     */
    public static class Util {
        /**
         * 获取session中的用户信息
         * 
         * @Title getCurrentUser
         * @author 吕凯
         * @date 2018年4月28日 下午1:54:10
         * @param session
         * @return SysUser
         */
        public static SysUser getSessionUser(HttpServletRequest request) {
            SysUser user = null;
            if (request != null) {
                try {
                    HttpSession session = request.getSession();
                    if (session != null) {
                        user = (SysUser) session.getAttribute(Web.Attr.SESSION_USER);
                    }
                } catch (Exception e) {
                    log.warn("", e);
                }
            }
            return user;
        }

        /**
         * 设置用户
         * 
         * @Title setSessionUser
         * @author 吕凯
         * @date 2018年6月20日 上午11:57:18
         * @param request
         * @param user
         * @return SysUser
         */
        public static SysUser setSessionUser(HttpServletRequest request, SysUser user) {
            HttpSession session = request.getSession();
            if (session != null) {
                session.setAttribute(Web.Attr.SESSION_USER, user);
                session.setAttribute(Web.Attr.USERID, user.getId());
            }
            return getSessionUser(request);
        }

        /**
         * 移除session中的user
         * 
         * @Title removeSessionUser
         * @author 吕凯
         * @date 2020年5月18日 上午9:10:28
         * @param request
         *            void
         */
        public static void removeSessionUser(HttpServletRequest request) {
            HttpSession session = request.getSession();
            if (session != null) {
                session.removeAttribute(Web.Attr.SESSION_USER);
                session.removeAttribute(Web.Attr.USERID);
            }
        }

        /**
         * 返回当前登录用户id
         * 
         * @Title getSessionUserId
         * @author 吕凯
         * @date 2018年6月12日 下午5:13:00
         * @param request
         * @return Long
         */
        public static Long getSessionUserId(HttpServletRequest request) {
            SysUser user = getSessionUser(request);
            if (user != null) {
                return user.getId();
            }
            return 0L;
        }

        /**
         * 返回当前用户的姓名
         * 
         * @Title getSessionUserName
         * @author 吕凯
         * @date 2020年4月15日 下午6:12:32
         * @param request
         * @return String
         */
        public static String getSessionUserName(HttpServletRequest request) {
            SysUser user = getSessionUser(request);
            if (user != null) {
                return user.getUserName();
            }
            return null;
        }
    }

    /**
     * 参数相关
     * 
     * @ClassName Parameter
     * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
     * @date 2018年6月15日 下午3:43:39
     *
     */
    public static class Parameter {
        /**
         * 根据参数名获取参数，加密后及不带搜索前缀的的也可获取，如equal_name，输入name也可以查询
         * 
         * @Title getParams
         * @author 吕凯
         * @date 2019年8月21日 下午1:48:07
         * @param request
         * @param paramName
         * @return String
         */
        public static String getParams(HttpServletRequest request, final String paramName) {
            if (request == null) {
                return null;
            }
            ArrayList<String> paramNamesList = getParamNamesList(request);
            String paramNameReal = getParamsName(request, paramNamesList, paramName);
            if (paramNameReal == null) {// 仍未找到，则循环参数处理器
                Set<String> keySet = PARAMS_QUERY_HANDLERS.keySet();
                for (String key : keySet) {
                    String paramNameDeal = key + paramName; // 拼接参数后再判断
                    paramNameDeal = getParamsName(request, paramNamesList, paramNameDeal);
                    if (paramNameDeal != null) {
                        paramNameReal = paramNameDeal;
                        break;
                    }
                }
            }
            String value = request.getParameter(paramNameReal);
            return value;
        }

        /**
         * 根据传入的参数名返回request中存在的Parameter，如果使用了加密会返回加密后对应的名字
         * 
         * @Title getParamsName
         * @author 吕凯
         * @date 2019年8月31日 上午9:07:04
         * @param request
         * @param paramName
         * @return String
         */
        public static String getParamsName(HttpServletRequest request, ArrayList<String> paramNamesList, final String paramName) {
            String paramNameReal = null;
            if (paramNamesList == null) {
                paramNamesList = getParamNamesList(request);
            }
            boolean hasThisParam = ListUtils.hasValue(paramNamesList, paramName);
            if (!hasThisParam) {// 不存在此变量，则尝试解密，加密的,先解密
                String paramNameDeal = encrypt(paramName);
                if (ListUtils.hasValue(paramNamesList, paramNameDeal)) {
                    paramNameReal = paramNameDeal;
                }
            } else { // 变量存在直接返回
                paramNameReal = paramName;
            }
            return paramNameReal;
        }

        /**
         * 参数多时建议用上面的方法
         * 
         * @Title getParamsName
         * @author 吕凯
         * @date 2019年8月31日 上午9:17:14
         * @param request
         * @param paramName
         * @return String
         */
        public static String getParamsName(HttpServletRequest request, final String paramName) {
            return getParamsName(request, null, paramName);
        }

        /**
         * 返回request中请求参数的list
         * 
         * @Title getParamNamesList
         * @author 吕凯
         * @date 2019年8月31日 上午9:09:21
         * @param request
         * @return ArrayList<String>
         */
        public static ArrayList<String> getParamNamesList(HttpServletRequest request) {
            Enumeration<String> paramNames = request.getParameterNames();
            ArrayList<String> paramNamesList = Collections.list(paramNames);
            return paramNamesList;
        }

        /**
         * 参数加密
         * 
         * @Title encrypt
         * @author 吕凯
         * @date 2019年8月21日 下午1:47:42
         * @param paramName
         * @return String
         */
        public static String encrypt(String paramName) {
            paramName = "e:" + SecurityUtil.queryEncrypt(paramName);
            return paramName;
        }

        /**
         * 参数解密,如未加密则原样返回
         * 
         * @Title decrypt
         * @author 吕凯
         * @date 2019年8月21日 下午1:47:54
         * @param value
         * @return String
         * @throws ParamsterValidException
         */
        public static String decrypt(String value) throws ParamsterValidException {
            if (hasEncrypt(value)) {
                try {
                    value = SecurityUtil.queryDecrypt(StringUtils.substringAfter(value, "e:"));
                } catch (Exception e) {
                    log.error("", e);
                    throw new ParamsterValidException("参数不合法(" + Web.Attr.ERROR_PARAMSTER_VALID_DECRYPT + ")！");
                }
                if (EorEncryptor.hasValidChar(value)) {
                    throw new ParamsterValidException("参数不合法(" + Web.Attr.ERROR_PARAMSTER_VALID_DECRYPT + ")！");
                }
            }
            return value;
        }

        /**
         * 获取参数是否加密
         * 
         * @Title hasEncrypt
         * @author 吕凯
         * @date 2019年8月31日 上午9:56:08
         * @param value
         * @return
         * @throws ParamsterValidException
         *             boolean
         */
        public static boolean hasEncrypt(String value) throws ParamsterValidException {
            return value != null && value.startsWith("e:");
        }

        /**
         * 获取是否需要处理参数
         * 
         * @Title hasDealParam
         * @author 吕凯
         * @date 2019年8月31日 上午9:55:55
         * @param value
         * @return
         * @throws ParamsterValidException
         *             boolean
         */
        public static boolean hasDealParam(String value) throws ParamsterValidException {
            return value != null && value.contains("_") && !value.startsWith("_");
        }

        /**
         * 获取参数处理的前缀
         * 
         * @Title getDealParamPrefix
         * @author 吕凯
         * @date 2019年8月31日 上午9:55:43
         * @param value
         * @return
         * @throws ParamsterValidException
         *             String
         */
        public static String getDealParamPrefix(final String value) throws ParamsterValidException {
            String prefix = null;
            if (StringUtils.isNotBlank(value)) {
                Optional<String> dealPrefix = Web.Parameter.getParamsQueryHandlers().keySet().stream()
                        .filter(prefixV -> value.startsWith(prefixV)).findFirst();
                if (dealPrefix.isPresent()) {
                    prefix = dealPrefix.get();
                }
            }
            return prefix;
        }

        public static int getInt(HttpServletRequest request, String name) {
            return ClassUtil.obj2int(getParams(request, name));
        }

        public static long getLong(HttpServletRequest request, String name) {
            return ClassUtil.obj2long(getParams(request, name));
        }

        public static String getString(HttpServletRequest request, String name) {
            return getParams(request, name);
        }

        public static double getDouble(HttpServletRequest request, String name) {
            return ClassUtil.obj2doulbe(getParams(request, name));
        }

        public static Date getDate(HttpServletRequest request, String name) {
            String dateStr = getString(request, name);
            if (StringUtils.isNotBlank(dateStr)) {
                return DateUtil.str2Date(dateStr);
            }
            return null;
        }

        /**
         * 根据参数名，返回参数list
         * 
         * @Title getList
         * @author 吕凯
         * @date 2017年3月3日 下午2:27:10
         * @param name
         * @return List<String>
         */
        public static List<String> getList(HttpServletRequest request, String name) {
            List<String> list = new ArrayList<>();
            String[] paramValues = getArray(request, name);
            if (paramValues != null) {
                list = Arrays.asList(paramValues);
            }
            return list;
        }

        /**
         * 
         * 根据参数名，返回参数set
         * 
         * @Title getSet
         * @author 吕凯
         * @date 2017年3月3日 下午3:04:23
         * @param name
         * @return Set<String>
         */
        public static Set<String> getSet(HttpServletRequest request, String name) {
            Set<String> set = new HashSet<>();
            String[] paramValues = getArray(request, name);
            if (paramValues != null) {
                set = new LinkedHashSet<>(Arrays.asList(paramValues));
            }
            return set;
        }

        /**
         * 根据参数名，返回参数数组
         * 
         * @Title getArray
         * @author 吕凯
         * @date 2017年3月3日 下午2:28:03
         * @param name
         * @return String[]
         */
        public static String[] getArray(HttpServletRequest request, String name) {
            return request.getParameterValues(name);
        }

        // 获取原始值，因为xss过滤器等前置过滤器可能已经处理过字段
        public static Object getParamOrgValue(HttpServletRequest request, String name) {
            Map<String, String[]> map = request.getParameterMap();
            if (map.containsKey(name)) {
                String[] vals = map.get(name);
                if (vals.length == 1) {
                    return vals[0]; // 只有一个时直接返回
                }
                return vals;
            }
            return null;
        }

        private static final Map<String, ParamsHandler> PARAMS_QUERY_HANDLERS = new HashMap<>(); // 参数处理器，key需要包含_
        public static final String PARAMS_QUERY_DEFAULT_KEY = "defalult"; // 默认处理
        static {
            ParamsHandler defalutHandler = new DefaultParamsHandler();
            PARAMS_QUERY_HANDLERS.put("equal_", defalutHandler); // 精确查询
            PARAMS_QUERY_HANDLERS.put("like_", defalutHandler); // 模糊查询
            PARAMS_QUERY_HANDLERS.put("like1_", defalutHandler); // 模糊查询"%" + paramValue
            PARAMS_QUERY_HANDLERS.put("like2_", defalutHandler); // 模糊查询paramValue + "%"
            PARAMS_QUERY_HANDLERS.put("like3_", defalutHandler); // 模糊查询
            PARAMS_QUERY_HANDLERS.put("like4_", defalutHandler); // 模糊查询 带，号
            PARAMS_QUERY_HANDLERS.put("date_", defalutHandler); // 日期查询
            PARAMS_QUERY_HANDLERS.put("time_", defalutHandler); // 时间查询
            PARAMS_QUERY_HANDLERS.put("month_", defalutHandler); // 月查询
            PARAMS_QUERY_HANDLERS.put("year_", defalutHandler); // 年查询
            PARAMS_QUERY_HANDLERS.put("range_", defalutHandler); // 范围查询
            PARAMS_QUERY_HANDLERS.put("area_", defalutHandler); // // 区域查询
            PARAMS_QUERY_HANDLERS.put(PARAMS_QUERY_DEFAULT_KEY, defalutHandler); // 默认，其他不符合条件的都走这个
        }

        /**
         * 注册新的参数处理器，也可对旧的进行覆盖
         * 
         * @Title registerParamsQueryHandler
         * @author 吕凯
         * @date 2019年7月18日 下午2:04:11
         * @param paramNameprefix
         * @param defalutHandler
         *            void
         */
        public static void registerParamsQueryHandler(String paramNameprefix, ParamsHandler defalutHandler) {
            PARAMS_QUERY_HANDLERS.put(paramNameprefix, defalutHandler);
        }

        public static Map<String, ParamsHandler> getParamsQueryHandlers() {
            return PARAMS_QUERY_HANDLERS;
        }

        public static QueryModel dealReqParams(HttpServletRequest request, QueryModel queryModel) {
            return dealReqParams(request, null, queryModel, null);
        }

        public static <T> QueryModel dealReqParams(HttpServletRequest request, Class<T> classOfT, QueryModel queryModel) {
            return dealReqParams(request, classOfT, queryModel, null);
        }

        public static QueryModel dealReqParams(HttpServletRequest request, QueryModel queryModel, String prefix) {
            return dealReqParams(request, null, queryModel, prefix);
        }

        /**
         * 指定类处理查询参数，则查询的字段必须为类中的属性
         * 
         * @Title dealReqParams
         * @author 吕凯
         * @param request
         * @param classOfT
         * @param queryModel
         * @param prefix
         * @return QueryModel
         * @throws ParamsterValidException
         */
        // 注意有未加密的参数，如p，csrf的令牌csft-token等
        public static <T> QueryModel dealReqParams(HttpServletRequest request, Class<T> classOfT, QueryModel queryModel, String prefix) {
            if (StringUtils.isNotBlank(prefix) && prefix.contains(".")) { // 以.分隔，不需要写 .
                prefix = StringUtils.substringBeforeLast(prefix, ".");
            }
            if (queryModel == null) {
                queryModel = new QueryModel();
            }
            Enumeration<String> attrs = request.getParameterNames();
            while (attrs.hasMoreElements()) {
                String paramName = (String) attrs.nextElement();
                String paramValue = request.getParameter(paramName);

                if (StringUtils.isNotBlank(paramValue) && !paramValue.equals("-99")) {// 排除空值 【字符型全部】和 负99【数值类型的全部】
                    if (hasEncrypt(paramName)) {// 加密的,先解密
                        paramName = decrypt(paramName);
                        if (!paramName.contains("_")) { // 解码出来不符合标准直接修改查询条件
                            paramName = "equal_" + paramName;
                        }
                    }

//                    if (paramName.contains(".")) {
//                        paramName = StringUtils.substringAfterLast(paramName, "."); // .用于区分多层对象 TODO 未实现
//                    }
                    if (StringUtils.isNotBlank(prefix)) {
                        if (!paramName.contains(prefix)) { // 不包含直接跳出
                            continue;
                        }
                        paramName = StringUtils.substringAfterLast(paramName, prefix + "."); // 如：user.equal_name
                    } else {
                        if (paramName != null && paramName.contains(".")) { // 包含点的直接跳出，点用于分组搜索，说明不在此组
                            continue;
                        }
                    }
                    if (!"_csrf".equals(paramName) && hasDealParam(paramName)) { // _csrf为csrf处理，默认包含_才处理
//                        String paramMatchKey = StringUtils.substringBefore(paramName, "_") + "_";
                        String paramMatchKey = getDealParamPrefix(paramName); // 获取处理前缀，根据处理前缀找到对应的处理类
                        ParamsHandler paramsHandler = PARAMS_QUERY_HANDLERS.get(paramMatchKey);
                        if (paramsHandler == null) {
                            paramsHandler = PARAMS_QUERY_HANDLERS.get(PARAMS_QUERY_DEFAULT_KEY);
                        }
                        String columnName = null; // 处理后的字段
                        // 把类字段转换成数据库字段
                        if (classOfT != null && !paramName.startsWith("_")) { // 下划线排除
                            // 此处是为了检验参数名称，不能对原来的queryModel进行操作，所以new了一个新对象
                            ParamsHandleResult result = paramsHandler.deal(paramName, paramValue, new QueryModel());
                            String cloNamedeal = result.getParamName(); // 获取字段名称

                            Description fieldDesc = AnnotationUtil.getFieldDescription(classOfT, cloNamedeal);
                            if (fieldDesc != null) { // 存在字段映射的情况下重新处理字段
                                columnName = result.getParamCondition() + fieldDesc.getDbName(); // 目标对象的主键对应数据库中的名字

                            } else { // 不存在说明不存在这个属性
                                log.warn("非法的搜索参数！" + cloNamedeal);
                                throw new ParamsterValidException("非法的搜索参数！(" + Web.Attr.ERROR_PARAMSTER_VALID_NONE + ")");
                            }
                        }
                        if (StringUtils.isEmpty(columnName)) { // 字段名称未进行转换
                            paramsHandler.deal(paramName, paramValue, queryModel);
                        } else {
                            paramsHandler.deal(columnName, paramValue, queryModel);
                        }

                    }
                }
            }
            return queryModel;
        }

        /**
         * 处理动态条件请求参数
         *
         * @author hansai
         * @date 2019-08-14 17:57
         */
        public static QueryModel dealDynamicConditionReqParams(HttpServletRequest request, QueryModel queryModel) {

            if (queryModel == null) {
                queryModel = new QueryModel();
            }

            // 左括号(用于分组) "0": 没有 "1":有
            String[] leftParentheses = request.getParameterValues("leftParenthesis");
            // 参数名称 "equal_xxx"
            String[] markConditionItems = request.getParameterValues("markConditionItem");
            // 参数值
            String[] conditionValues = request.getParameterValues("conditionValue");
            // 右括号(用于分组) "0": 没有 "1":有
            String[] rightParentheses = request.getParameterValues("rightParenthesis");
            // 动态条件拼接 and 还是 or
            String[] relationships = request.getParameterValues("relationship");

            // 判断数据有效性
            boolean hasDynamicCondition = verifyDynamicConditions(leftParentheses, markConditionItems, conditionValues, rightParentheses,
                    relationships);

            if (hasDynamicCondition) {
                // 动态条件个数
                int dynamicConditionLength = markConditionItems.length;
                List<Integer> leftParenthesis = Arrays.stream(leftParentheses).map(ClassUtil::obj2int).collect(Collectors.toList());
                List<Integer> rightParenthesis = Arrays.stream(rightParentheses).map(ClassUtil::obj2int).collect(Collectors.toList());
                // 判断括号是否完全匹配
                boolean isBracketsMatch = verifyLeftAndRightBracketsMatch(dynamicConditionLength, leftParenthesis, rightParenthesis);
                if (isBracketsMatch) {
                    // 动态设置的条件最外层套个左右括号
                    queryModel.appendLeftParenthesis();
                    for (int i = 0; i < markConditionItems.length; i++) {

                        if (leftParenthesis.get(i) == StaticParams.DYNAMIC_CONDITION_BRACKETS) {
                            queryModel.appendLeftParenthesis();
                        }
                        String paramName = markConditionItems[i];
                        String paramValue = conditionValues[i];

                        if (StringUtils.isNotBlank(paramValue) && !paramValue.equals("-99")) {// 排除空值 【字符型全部】和 负99【数值类型的全部】
                            if (paramName.contains(".")) {
                                paramName = StringUtils.substringAfterLast(paramName, "."); // .用于区分多层对象
                            }
                            if (hasEncrypt(paramName)) {// 加密的,先解密
                                paramName = decrypt(paramName);
                                if (!paramName.contains("_")) { // 解码出来不符合标准直接修改查询条件
                                    paramName = "equal_" + paramName;
                                }
                            }
                            if (!"_csrf".equals(paramName) && paramName.contains("_")) { // _csrf为csrf处理
                                String paramMatchKey = StringUtils.substringBefore(paramName, "_") + "_";
                                ParamsHandler paramsHandler = PARAMS_QUERY_HANDLERS.get(paramMatchKey);
                                if (paramsHandler == null) {
                                    paramsHandler = PARAMS_QUERY_HANDLERS.get(PARAMS_QUERY_DEFAULT_KEY);
                                }
                                paramsHandler.deal(paramName, paramValue, queryModel);

                                if (rightParenthesis.get(i) == StaticParams.DYNAMIC_CONDITION_BRACKETS) {
                                    queryModel.appendRightParenthesis();
                                }

                                // 动态条件查询拼接部分
                                int relationship = ClassUtil.obj2int(relationships[i]);
                                if (StaticParams.DYNAMIC_CONDITION_OR == relationship && i < dynamicConditionLength - 1) {
                                    queryModel.appendOr();
                                }

                            }
                        }
                    }
                    // 动态设置的条件最外层套个左右括号
                    queryModel.appendRightParenthesis();
                    // 调整sql
                    queryModel.adjustmentDynamicCondition();
                }
            }
            return queryModel;
        }

        /**
         * 分组括号是否完全匹配
         *
         * @author hansai
         * @date 2019-08-15 08:20
         */
        private static boolean verifyLeftAndRightBracketsMatch(int dynamicConditionLength, List<Integer> leftParenthesis,
                List<Integer> rightParenthesis) {
            boolean isBracketsMatch = true;
            // 左括号往里压一个元素，右括号出一个元素，如果发生异常或者最后stack的大小不为0，那么就是不匹配的。
            Deque<Integer> bracketsArrayDeque = new ArrayDeque<>();
            for (int i = 0; i < dynamicConditionLength; i++) {
                boolean hasLeftParenthesis = leftParenthesis.get(i) == StaticParams.DYNAMIC_CONDITION_BRACKETS;
                if (hasLeftParenthesis) {
                    bracketsArrayDeque.push(StaticParams.DYNAMIC_CONDITION_BRACKETS);
                }
                boolean hasRightParenthesis = rightParenthesis.get(i) == StaticParams.DYNAMIC_CONDITION_BRACKETS;
                if (hasRightParenthesis) {
                    try {
                        bracketsArrayDeque.pop();
                    } catch (Exception e) {
                        isBracketsMatch = false;
                        break;
                    }
                }
            }
            isBracketsMatch = isBracketsMatch && bracketsArrayDeque.isEmpty();
            return isBracketsMatch;
        }

        /**
         * 校验动态查询条件有效性,是否要进行动态条件查询
         *
         * @author hansai
         * @date 2019-08-14 17:21
         */
        private static boolean verifyDynamicConditions(String[]... dynamicConditions) {
            boolean isOk = true;
            if (dynamicConditions == null) {
                isOk = false;
            } else {
                // 共有几项数据
                int length = dynamicConditions.length;

                // 第一项数据的长度
                int conditionLength = 0;
                for (int i = 0; i < length; i++) {
                    if (dynamicConditions[i] == null) {
                        isOk = false;
                        break;
                    } else {
                        if (i == 0) {
                            conditionLength = dynamicConditions[i].length;
                        } else {
                            if (conditionLength != dynamicConditions[i].length) {
                                isOk = false;
                                break;
                            }
                        }
                    }

                }
            }
            return isOk;
        }

    }

}
